<?php

declare(strict_types=1);

namespace App\CustHub\Service;

use App\Common\Libary\Third\Pdd;
use App\Common\Libary\Third\Request\PddRequest\PddDdkAuthorityQueryRequest;
use App\Common\Libary\Third\Request\PddRequest\PddDdkRpPromUrlGenerateRequest;
use App\Common\Redis\TaggedCache;
use App\CustHub\Mapper\ChAffiliatePidMapper;
use App\CustHub\Model\ChAffiliateAccount;
use App\CustHub\Model\ChAffiliatePid;
use Mine\Abstracts\AbstractService;
use Mine\Exception\NormalStatusException;
use Psr\SimpleCache\CacheInterface;
use function Hyperf\Collection\data_get;

class AffiliatePidService extends AbstractService
{
    public $mapper;

    private TaggedCache $taggedCache;

    private CacheInterface  $cache;

    private const TAG_KEY = 'affiliate_pid_tag';

    public function __construct(ChAffiliatePidMapper $mapper,  TaggedCache $taggedCache,  CacheInterface $cache)
    {
        $this->mapper = $mapper;
        $this->taggedCache = $taggedCache;
        $this->cache = $cache;
    }

    public function getPidInfo(mixed $id)
    {
        $key = 'affiliate_pid_info:'.$id;
        $info = $this->cache->get($key);
        if(empty($info)){
            $info = ChAffiliatePid::query()
                ->with(['account'])
                ->where('id',$id)
                ->first();
            if(!empty($info)){
                $this->taggedCache->setWithTags($key, $info, [ChAffiliateAccount::ACCOUNT_TAG_KEY.$info->account->id,ChAffiliatePid::TAG_KEY.$id],3600);
            }
        }
        return $info;
    }

    public function flushByTag(mixed $id): bool
    {
        return $this->taggedCache->flushTag(self::TAG_KEY.$id);
    }

    public function save(array $data): mixed
    {
        $id = $this->mapper->save($data);
        $id && $this->flushByTag($id);
        return $id;
    }

    public function update(mixed $id, array $data): bool
    {
        $rst = $this->mapper->update($id, $data);
        $rst && $this->flushByTag($id);
        return $rst;
    }

    public function deletePid(mixed $id): bool
    {
        $this->mapper->delete([$id]);
        $this->flushByTag($id);
        return true;
    }

    /**
     * 获取pid授权备案链接
     * @param mixed $id
     * @return array|mixed
     */
    public function getOauthUrl(mixed $id): mixed
    {
        $pidInfo = $this->getPidInfo($id);
        if(empty($pidInfo)){
            throw new NormalStatusException('请选择推广平台');
        }

//        $customParameters = [
//            'uid' => $pidInfo->account->uid,
//            'ext' => []
//        ];

        $pdd = new Pdd();
        $oauthId = generateOrderNumber();

        $data = (new PddDdkRpPromUrlGenerateRequest())
            ->setPIdList([$pidInfo->pid])
            ->setCustomParameters($oauthId)
            ->setGenerateShortUrl(true)
            ->setChannelType(10);

        $res = $pdd->setAccessToken($pidInfo->account->access_token)
            ->setThrowError(true)
            ->promUrlGenerate($data);
        if($res['rp_promotion_url_generate_response']){
            $res['rp_promotion_url_generate_response']['oauthId']  = $oauthId;
            $res['rp_promotion_url_generate_response']['oauthQrCodeUrl'] = create_qrcode_url($res['rp_promotion_url_generate_response']['url_list'][0]['short_url']);
            return $res['rp_promotion_url_generate_response'];
        }
        throw new NormalStatusException($res['error_response']['error_msg']);
    }

    public function checkPidHasOauth(array $params): bool
    {
        $pidInfo = $this->getPidInfo($params['id']);
        if(empty($pidInfo)){
            throw new NormalStatusException('授权不存在',5002);
        }

        if($pidInfo->oauth_id){
            throw new NormalStatusException('已授权',5002);
        }

        $oauthId = $params['oauthId'];
        if(!$oauthId){
            throw new NormalStatusException('授权不存在',5002);
        }

        $data = (new PddDdkAuthorityQueryRequest())
            ->setPid($pidInfo->pid)
            ->setCustomParameters($oauthId);

        $pdd = new Pdd();
        $res = $pdd->setAccessToken($pidInfo->account->access_token)
            ->setThrowError(true)
            ->checkPidHasOauth($data);

        if($res){
            $this->update($pidInfo->id,['oauth_id'=>$oauthId]);
            $this->flushByTag($pidInfo->id);
            return true;
        }
        return false;
    }

}